package com.aabbc.redis.service.impl;

import com.aabbc.redis.entity.User;
import com.aabbc.redis.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RLock;
import org.redisson.api.RQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * UserServiceImpl
 *
 * @author: <a href="mailto:chenfenghai@oristartech.com">chenfenghai</a>
 * @version: 1.0
 * @date: 2019-11-08 17:43
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    private static final Map<Long, User> USER_MAP = new HashMap<>();

    @Autowired
    private RedissonClient redissonClient;

    static {
        USER_MAP.put(1L, new User(1L, "1geekdigging.com", 18));
        USER_MAP.put(2L, new User(2L, "2geekdigging.com", 19));
        USER_MAP.put(3L, new User(3L, "3geekdigging.com", 20));
    }

    @CachePut(value = "user", key = "#user.id")//写入缓存，key为user.id,一般该注解标注在新增方法上
    @Override
    public User save(User user) {
        USER_MAP.put(user.getId(), user);
        log.info("进入 save 方法，当前存储对象：{}",  user);
        return user;
    }

    @Cacheable(value = "user", key = "#id")//如果缓存存在，直接读取缓存值；如果缓存不存在，则调用目标方法，并将结果放入缓存
    @Override
    public User get(Long id) {
        log.info("进入 get 方法，当前获取对象：{}",  USER_MAP.get(id));
        return USER_MAP.get(id);
    }

    @CacheEvict(value = "user", key = "#id")//根据key清除缓存，一般该注解标注在修改和删除方法上
    @Override
    public void delete(Long id) {
        USER_MAP.remove(id);
        log.info("进入 delete 方法，删除成功");
    }

    @Override
    @CacheEvict(value="user",allEntries=true)//方法调用后清空所有缓存
    public void deleteAll1() {

    }

    @Override
    @CacheEvict(value="user",beforeInvocation=true)//方法调用前清空所有缓存
    public void deleteAll2() {

    }

    @Override
    public void asynAddCode(String key){
        RLock lock = redissonClient.getLock("codelock");
        lock.lock(1, TimeUnit.MINUTES);
        try {
            RBlockingQueue<String> codeQueue = redissonClient.getBlockingQueue(key);
            if(codeQueue.size() > 10){
                log.info("lock");
                return;
            }
            IntStream.range(1, 6).forEach(i -> {
                String code = RandomStringUtils.randomNumeric(8);
                if(!codeQueue.contains(code)){
                    codeQueue.addAsync(code);
                }
            });
        }finally {
            lock.unlock();
        }
    }
}
